///图片压缩
import 'dart:io';
import 'dart:ui' as ui;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:flutter/services.dart';
import 'dart:typed_data';

class CompressImageFile {
  static Future<File> saveFile(List<int> fileByte,
      {String path = "/compressImg.jpg"}) async {
    var dir = await path_provider.getTemporaryDirectory();
    var targetPath = dir.absolute.path + path;
    File file = File(targetPath);
    await file.writeAsBytes(fileByte);
    return file;
  }

  static Future<File> compressImageData(List<int> toCompressImgData,
      {int maxSize = 300 * 1024}) async {
    List<int> res;
    try {
      ///先改变为jpg格式并初步压缩，判断是否满足，不满足再继续压缩
      List<int> finalImageFile = await doCompress(toCompressImgData);
      if (finalImageFile.length <= maxSize) return saveFile(finalImageFile);
      List compressionQualityArr = [];
      int avg = 95;
      int value = avg;
      for (int i = 0; i < 95; i++) {
        value = avg - i;
        compressionQualityArr.add(value);
      }

      ///使用二分法搜索
      res = await halfFunction(compressionQualityArr, finalImageFile, maxSize);
      if (res == null) {
        Completer<ui.Image> completer = new Completer<ui.Image>();
        MemoryImage(finalImageFile).resolve(ImageConfiguration()).addListener(
            ImageStreamListener(
                    (ImageInfo info, bool _) => completer.complete(info.image)));
        ui.Image image = await completer.future;
        int minH = image.height;
        print('二分法没找到 修改尺寸 $minH');

        ///二分法没找到 修改尺寸
        while (res == null) {
          ///每次减100像素
          minH -= 100;
          res = await halfFunction(
              compressionQualityArr, finalImageFile, maxSize,
              minH: minH);
        }
      } else {
        print('二分法找到了 size: ${res.length}');
      }
    } catch (e) {
      print('压缩失败：$e');
    }
    File resFile = await saveFile(res);

    return resFile;
  }

  static Future<File> compressImageFile(File toCompressImgFile,
      {int maxSize = 300 * 1024}) async {
    List<int> res;
    try {
      ///先改变为jpg格式并初步压缩，判断是否满足，不满足再继续压缩
      List<int> finalImageFile =
      await doCompress(toCompressImgFile.readAsBytesSync());
      if (finalImageFile.length <= maxSize) return saveFile(finalImageFile);
      List compressionQualityArr = [];
      int avg = 95;
      int value = avg;
      for (int i = 0; i < 95; i++) {
        value = avg - i;
        compressionQualityArr.add(value);
      }

      ///使用二分法搜索
      res = await halfFunction(compressionQualityArr, finalImageFile, maxSize);
      if (res == null) {
        Completer<ui.Image> completer = new Completer<ui.Image>();
        MemoryImage(finalImageFile).resolve(ImageConfiguration()).addListener(
            ImageStreamListener(
                    (ImageInfo info, bool _) => completer.complete(info.image)));
        ui.Image image = await completer.future;
        int minH = image.height;
        print('二分法没找到 修改尺寸 $minH');

        ///二分法没找到 修改尺寸
        while (res == null) {
          ///每次减100像素
          minH -= 100;
          res = await halfFunction(
              compressionQualityArr, finalImageFile, maxSize,
              minH: minH);
        }
      } else {
        print('二分法找到了 size: ${res.length}');
      }
    } catch (e) {
      print('压缩失败：$e');
    }
    File resFile = await saveFile(res);

    return resFile;
  }

  ///二分法
  static Future<List<int>> halfFunction(
      List arr, List<int> sourceImg, int maxSize,
      {int minH = 1024}) async {
    List<int> tempData;
    int start = 0;
    int end = arr.length - 1;
    int index = 0;
    List<int> finalImageData;
    int difference = double.maxFinite.toInt();
    print('开始二分法');
    while (start <= end) {
      index = (start + (end - start) / 2).toInt();
      finalImageData =
      await doCompress(sourceImg, quality: arr[index], minH: minH);
      int sizeOrigin = finalImageData.length;
      if (sizeOrigin > maxSize) {
        start = index + 1;
      } else if (sizeOrigin < maxSize) {
        if (maxSize - sizeOrigin < difference) {
          difference = maxSize - sizeOrigin;
          tempData = finalImageData;
        }
        if (index <= 0) {
          break;
        }
        end = index - 1;
      } else {
        break;
      }
    }
    return tempData;
  }

  static Future<List<int>> doCompress(List<int> file,
      {int minH = 4096, int quality = 95}) async {
//    var dir = await path_provider.getTemporaryDirectory();
//    var now = new DateTime.now();
//    var targetPath = dir.absolute.path + "/${now.toString()}.jpg";
    var result = await FlutterImageCompress.compressWithList(file,
        minHeight: minH, quality: quality);
    return result;
  }
}
